#include "WidgetExtractIcon.h"

#include <QLineEdit>
#include <QListWidget>
#include <QPushButton>
#include <QTextEdit>
#include <QFileDialog>
#include <QScopedArrayPointer>
#include <QPixmap>
#include <QFileInfo>
#include <QDir>
#include <QLayout>
#include <QDebug>

WidgetExtractIcon::WidgetExtractIcon(QWidget *parent)
    : QWidget(parent)
{
    setWindowTitle(QStringLiteral("提取exe/dll/icon文件图标"));
    resize(400, 400);

    m_pSourceLineEdit = new QLineEdit(this);
    m_pSaveLineEdit = new QLineEdit(this);
    m_pListWidget = new QListWidget(this);
    m_pTextEdit = new QTextEdit(this);
    m_pSourceButton = new QPushButton(this);
    m_pSaveButton = new QPushButton(this);
    m_pExtractButton = new QPushButton(this);

    m_pSourceLineEdit->setReadOnly(true);
    m_pSaveLineEdit->setReadOnly(true);
    m_pTextEdit->setReadOnly(true);

    m_pSourceButton->setText(QStringLiteral("源文件"));
    m_pSaveButton->setText(QStringLiteral("保存路径"));
    m_pExtractButton->setText(QStringLiteral("提取"));

    QGridLayout *pLayout = new QGridLayout(this);
    pLayout->addWidget(m_pSourceLineEdit, 0, 0);
    pLayout->addWidget(m_pSourceButton, 0, 1);
    pLayout->addWidget(m_pSaveLineEdit, 1, 0);
    pLayout->addWidget(m_pSaveButton, 1, 1);
    pLayout->addWidget(m_pListWidget, 2, 0, 1, 2);
    pLayout->addWidget(m_pTextEdit, 3, 0, 1, 2);
    pLayout->addWidget(m_pExtractButton, 4, 1);
    pLayout->setSpacing(10);
    pLayout->setMargin(10);

    m_pListWidget->setViewMode(QListWidget::IconMode );
    m_pListWidget->setResizeMode(QListWidget::Adjust);
    m_pListWidget->setMovement(QListWidget::Static);

    connect(m_pSourceButton, &QPushButton::clicked, this, &WidgetExtractIcon::onSourceSelected);
    connect(m_pSaveButton, &QPushButton::clicked, this, &WidgetExtractIcon::onSaveSelected);
    connect(m_pExtractButton, &QPushButton::clicked, this, &WidgetExtractIcon::onExtract);
}

WidgetExtractIcon::~WidgetExtractIcon()
{

}

// 设置源文件路径
void WidgetExtractIcon::onSourceSelected()
{
    QString fileName = QFileDialog::getOpenFileName(this, QString("Open File"),
                                                    "/home",
                                                    QString("All files (*.*);;DLL files (*.exe *.dll);;Images (*.png *.xpm *.jpg)"));
    if (!fileName.isEmpty())
        m_pSourceLineEdit->setText(fileName);
}

// 设置保存路径
void WidgetExtractIcon::onSaveSelected()
{
    QString dir = QFileDialog::getExistingDirectory(this, QString("Open Directory"),
                                                    "/home",
                                                    QFileDialog::ShowDirsOnly
                                                    | QFileDialog::DontResolveSymlinks);
    if (!dir.isEmpty())
        m_pSaveLineEdit->setText(dir);
}

// 提取
void WidgetExtractIcon::onExtract()
{
    // 删除之前的 item
    int count = m_pListWidget->count();
    for(int i = 0 ; i < count; ++i) {
        QListWidgetItem *item = m_pListWidget->takeItem(0);
        delete item;
    }

    m_pTextEdit->clear();

    const QString sourceFile = m_pSourceLineEdit->text();
    const QString fileRoot = m_pSaveLineEdit->text();
    QString imageFileRoot = fileRoot.isEmpty() ? QDir::currentPath() : fileRoot;
    const QFileInfo imageFileRootInfo(imageFileRoot);

    // ExtractIconEx 从限定的可执行文件、动态链接库（DLL）、或者图标文件中生成图标句柄数组
    const UINT iconCount = ExtractIconEx((wchar_t *)sourceFile.utf16(), -1, 0, 0, 0);
    if (!iconCount) {
        qDebug() << QString("%1 does not appear to contain icons.").arg(sourceFile);
        return;
    }

    QScopedArrayPointer<HICON> icons(new HICON[iconCount]);
    bool large = true;
    const UINT extractedIconCount = large ?
        ExtractIconEx((wchar_t *)sourceFile.utf16(), 0, icons.data(), 0, iconCount) :
        ExtractIconEx((wchar_t *)sourceFile.utf16(), 0, 0, icons.data(), iconCount);
    if (!extractedIconCount) {
        m_pTextEdit->append(QStringLiteral("从 %1 提取图标失败").arg(sourceFile));
        return;
    }

    m_pTextEdit->append(QString("%1 包含 %2 个图标").arg(sourceFile).arg(extractedIconCount));

    imageFileRoot = imageFileRootInfo.absoluteFilePath() + QLatin1Char('/') + QFileInfo(sourceFile).baseName();
    for (UINT i = 0; i < extractedIconCount; ++i) {
        const QPixmap pixmap = QtWin::fromHICON(icons[i]);
        if (pixmap.isNull()) {
            m_pTextEdit->append(QStringLiteral("图标转换错误"));
            continue;
        }

        // 添加新 item
        QListWidgetItem *pItem = new QListWidgetItem(m_pListWidget);
        pItem->setText(QString("%1 * %2").arg(pixmap.height()).arg(pixmap.width()));
        pItem->setIcon(QIcon(pixmap));
        m_pListWidget->addItem(pItem);

        // 保存图片
        const QString fileName = QString::fromLatin1("%1%2.png").arg(imageFileRoot)
            .arg(i, 3, 10, QLatin1Char('0'));
        if (!pixmap.save(fileName)) {
            m_pTextEdit->append(QStringLiteral("写入图像文件 %1 错误").arg(fileName));
            continue;
        }

        m_pTextEdit->append(QStringLiteral("保存图片文件 %1.").arg(QDir::toNativeSeparators(fileName)));
    }
}
